package com.itheima.leetcode;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * TinyURL 的加密与解密
 */
public class MinStackLeetcode535 {

    public static void main(String[] args) {
        Codec codec = new Codec();
        String encoded = codec.encode("https://leetcode.cn/problems/1");
        System.out.println(encoded);
        encoded = codec.encode("https://leetcode.cn/problems/2");
        System.out.println(encoded);

        CodecHashCode codec2 = new CodecHashCode();
        String encoded2 = codec2.encode("https://leetcode.cn/problems/1");
        System.out.println(encoded2);
        encoded2 = codec2.encode("https://leetcode.cn/problems/2");
        System.out.println(encoded2);

        CodecSequence codec3 = new CodecSequence();
        String encoded3 = codec3.encode("https://leetcode.cn/problems/1");
        System.out.println(encoded3);
        encoded3 = codec3.encode("https://leetcode.cn/problems/2");
        System.out.println(encoded3);
    }

    static class Codec {

        private Map<String, String> longToShort = new HashMap<>();
        private Map<String, String> shortToLong = new HashMap<>();
        private static final String SHORT_PREFIX = "http://tinyurl.com/";

        public String encode(String longUrl) {
            String shortUrl = longToShort.get(longUrl);
            if (null != shortUrl) {
                return shortUrl;
            }
            // 生成短网址
            while (true) {
                int id = ThreadLocalRandom.current().nextInt(); // int
                shortUrl = SHORT_PREFIX + id;
                if (shortToLong.containsKey(shortUrl)) {

                    longToShort.put(longUrl, shortUrl);
                    shortToLong.put(shortUrl, longUrl);
                    break;
                }
                longToShort.put(longUrl, shortUrl);
                shortToLong.put(shortUrl, longUrl);
            }
            return shortUrl;
        }

        public String decode(String shortUrl) {
            return shortToLong.get(shortUrl);
        }
    }

    static class CodecHashCode {

        private Map<String, String> longToShort = new HashMap<>();
        private Map<String, String> shortToLong = new HashMap<>();
        private static final String SHORT_PREFIX = "http://tinyurl.com/";

        public String encode(String longUrl) {
            String shortUrl = longToShort.get(longUrl);
            if (null != shortUrl) {
                return shortUrl;
            }
            // 生成短网址
            int id = longUrl.hashCode();
            shortUrl = SHORT_PREFIX + id;
            while (true) {
                shortUrl = SHORT_PREFIX + id;
                if (shortToLong.containsKey(shortUrl)) {

                    longToShort.put(longUrl, shortUrl);
                    shortToLong.put(shortUrl, longUrl);
                    break;
                }
                longToShort.put(longUrl, shortUrl);
                shortToLong.put(shortUrl, longUrl);
                id++;
            }
            return shortUrl;
        }

        public String decode(String shortUrl) {
            return shortToLong.get(shortUrl);
        }
    }

    static class CodecSequence {

        private static final char[] toBase62 = {
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
                'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
        };

        public static String toBase62(int number) {
            StringBuilder sb = new StringBuilder();
            while (0 < number) {
                int r = number % 62;
                sb.append(toBase62[r]);
                number = number / 62;
            }
            return sb.toString();
        }

        private Map<String, String> longToShort = new HashMap<>();
        private Map<String, String> shortToLong = new HashMap<>();
        private static final String SHORT_PREFIX = "http://tinyurl.com/";
        private static int id = 1;

        public String encode(String longUrl) {
            String shortUrl = longToShort.get(longUrl);
            if (null != shortUrl) {
                return shortUrl;
            }
            // 生成短网址
            shortUrl = SHORT_PREFIX + toBase62(id);
            longToShort.put(longUrl, shortUrl);
            shortToLong.put(shortUrl, longUrl);
            id++;
            return shortUrl;
        }

        public String decode(String shortUrl) {
            return shortToLong.get(shortUrl);
        }
    }
}
